import axios from 'axios'
import { stringify } from 'qs'

import getFormattedString from '../utils/date'
import { info, success, warn } from '../utils/output'
import { responsParser } from '../utils/parser'
import checker from '../utils/checker'

import LocationModel from '../model/location.model'
import UserinfoModel from '../model/userinfo.model'
import HeaderModel from '../model/header.model'

type Params = {
  id: string
  id2: string
}

// 运行时的日期 作为提交的参数之一
const today = getFormattedString()

// 提交请求的响应结果
const responsMap: Map<string, boolean> = new Map([
  ['登记失败', false],
  ['提交成功', true],
  [today + '登记已存在', true]
])

// 不带地址的一键登记，返回值代表是否执行成功
const signIn = async (
  username: string,
  url: string,
  id: string,
  headers: HeaderModel
): Promise<string> => {
  // 需要携带的 params 参数
  const params: Params = { id, id2: today }
  // 遇到的坑：axios 会自动去掉 params 中值为 undefined 或者空字符串(falsy)的键
  // 而请求时如果不携带 adds 和 addsxy，ISP 会认为没有开启定位，因此这里只能写成 'undefined' 而不能用 undefined
  const { data } = await axios.get(url, {
    params: { ...params, adds: 'undefined', addsxy: 'undefined' },
    headers: { ...headers }
  })
  // 解析页面返回结果
  const msg = responsParser(data)
  const res = responsMap.get(msg!)!
  res || warn(`${username} 一键登记失败，尝试常规登记...`)
  return `${username} 一键登记成功，登记信息：${msg}`
}

// 带有地址的常规登记，无返回值，失败了直接抛出错误，代表打卡操作失败了
const signInWithLocation = async (
  username: string,
  url: string,
  location: LocationModel,
  headers: HeaderModel
): Promise<string> => {
  info(username + ' 的地址信息如下：')
  console.log(location)
  const { province, city, area } = location
  const body: string = stringify({
    province,
    city,
    area,
    hcode: '绿码',
    kesou: '否',
    zhengduan: '',
    fare: '否',
    wls: '否'
  })
  const nonriskParams: string = '&wuhan=%E5%90%A6&wuhan=%E5%90%A6&wuhan=%E5%90%A6&action=add&adds=&addsxy='
  const { data } = await axios.post(url, body + nonriskParams, { headers: { ...headers } })

  // 解析页面返回结果
  const msg = responsParser(data)
  const res = responsMap.get(msg!)!
  checker(res, '', '常规登记出错')
  return `${username} 常规登记成功，登记信息：${msg}`
}

const submitRequest = async (
  regularSignIn: boolean,
  userinfo: UserinfoModel,
  id: string,
  headers: HeaderModel,
  ...urls: Array<string>
): Promise<string> => {
  // 一键登记的地址、常规登记的地址
  const [url, generalUrl] = urls
  const { username, province, city, area } = userinfo
  const location = { province, city, area } as LocationModel
  // 判断是否为常规登记，一键登记失败则常规登记
  return !regularSignIn
    && await signIn(username, url, id, headers)
    || await signInWithLocation(username, generalUrl, location, headers)
}

export default submitRequest
